<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>大模型微调交互式可视化</title>
    <script src="https://cdn.tailwindcss.com"></script>
    <link rel="preconnect" href="https://fonts.googleapis.com">
    <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
    <link href="https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap" rel="stylesheet">
    <style>
        body {
            font-family: 'Inter', sans-serif; /* 应用 Inter 字体 */
            scroll-behavior: smooth;
        }
        /* 突出显示的可训练参数/模块 */
        .trainable {
            border: 2px dashed #34D399; /* 绿色虚线边框 */
            background-color: rgba(16, 185, 129, 0.1); /* 淡绿色背景 */
            transition: all 0.3s ease-in-out;
        }
        /* 冻结的参数/模块 */
        .frozen {
            border: 2px solid #9CA3AF; /* 灰色实线边框 */
            background-color: #F3F4F6; /* 浅灰色背景 */
            opacity: 0.7;
            transition: all 0.3s ease-in-out;
        }
        /* 简单的 LLM 层表示 */
        .llm-layer {
            @apply h-10 w-full rounded flex items-center justify-center text-sm font-medium text-gray-700 mb-1 transition-all duration-300 ease-in-out;
        }
        /* 适配器模块 */
        .adapter-module {
             @apply h-8 w-16 rounded flex flex-col items-center justify-center text-xs font-medium text-gray-700 mx-auto border border-blue-500 bg-blue-100 transition-all duration-300 ease-in-out;
        }
         /* LoRA 矩阵 */
        .lora-matrix {
            @apply h-10 w-6 rounded flex items-center justify-center text-xs font-medium text-gray-700 border border-purple-500 bg-purple-100 transition-all duration-300 ease-in-out;
        }
        /* 提示向量 */
        .prompt-vector {
             @apply h-8 w-8 rounded-full flex items-center justify-center text-xs font-medium text-white bg-orange-500 transition-all duration-300 ease-in-out shadow-md;
        }
        /* 激活按钮样式 */
        .active-btn {
            @apply bg-indigo-600 text-white;
        }
        /* 滚动条优化 (可选) */
        ::-webkit-scrollbar {
            width: 8px;
        }
        ::-webkit-scrollbar-track {
            background: #f1f1f1;
            border-radius: 10px;
        }
        ::-webkit-scrollbar-thumb {
            background: #888;
            border-radius: 10px;
        }
        ::-webkit-scrollbar-thumb:hover {
            background: #555;
        }
        /* 动画效果 */
        @keyframes fadeIn {
            from { opacity: 0; transform: translateY(10px); }
            to { opacity: 1; transform: translateY(0); }
        }
        .fade-in {
            animation: fadeIn 0.5s ease-out forwards;
        }
         /* 侧边导航固定 */
        .sticky-nav {
            position: sticky;
            top: 1rem; /* 根据需要调整 */
            max-height: calc(100vh - 2rem); /* 限制最大高度 */
            overflow-y: auto; /* 如果内容过多则允许滚动 */
        }
    </style>
</head>
<body class="bg-gray-50 text-gray-800">

    <div class="container mx-auto px-4 py-8 max-w-7xl">
        <h1 class="text-3xl font-bold text-center text-indigo-700 mb-10">大模型微调：交互式可视化指南</h1>

        <div class="flex flex-col lg:flex-row gap-8">
            <nav class="lg:w-1/4 mb-8 lg:mb-0 lg:sticky-nav">
                <h2 class="text-lg font-semibold mb-3 text-gray-700">导航</h2>
                <ul class="space-y-2">
                    <li><a href="#intro" class="text-indigo-600 hover:underline">引言：为何微调？</a></li>
                    <li><a href="#scope" class="text-indigo-600 hover:underline">微调范围与原则</a></li>
                    <li><a href="#methods-overview" class="text-indigo-600 hover:underline">微调方法概览</a></li>
                    <li><a href="#full-finetuning" class="text-indigo-600 hover:underline">全量微调 (Full Fine-tuning)</a></li>
                    <li><a href="#peft-overview" class="text-indigo-600 hover:underline">PEFT 高效微调</a></li>
                    <li><a href="#peft-model" class="text-indigo-600 hover:underline">&nbsp;&nbsp;&nbsp;├ 模型微调</a></li>
                    <li><a href="#peft-prompt" class="text-indigo-600 hover:underline">&nbsp;&nbsp;&nbsp;├ 提示微调 (Prompt-based)</a></li>
                    <li><a href="#peft-adapter" class="text-indigo-600 hover:underline">&nbsp;&nbsp;&nbsp;├ 外部模块微调 (Adapter-based)</a></li>
                     <li><a href="#rlhf" class="text-indigo-600 hover:underline">强化学习 (RLHF)</a></li>
                    <li><a href="#summary" class="text-indigo-600 hover:underline">总结</a></li>
                </ul>
            </nav>

            <main class="lg:w-3/4">
                <section id="intro" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                    <h2 class="text-2xl font-semibold text-indigo-600 mb-4">引言：为何微调？</h2>
                    <p class="mb-4">大语言模型（LLM）虽然强大，但通用模型往往无法完美契合特定的业务场景或满足特定的需求。微调（Fine-tuning）允许我们在预训练模型的基础上，使用特定领域的数据进行进一步训练，使其更好地适应特定任务，提升效果，同时也能在一定程度上解决数据隐私和安全问题。</p>
                    <p class="font-medium">微调的核心价值：</p>
                    <ul class="list-disc list-inside space-y-1 text-gray-700 mb-4">
                        <li><strong class="text-indigo-500">领域适应：</strong> 让模型掌握特定行业或任务的知识和语言风格。</li>
                        <li><strong class="text-indigo-500">性能提升：</strong> 在特定任务上超越通用模型的表现。</li>
                        <li><strong class="text-indigo-500">数据安全：</strong> 对于隐私要求高的场景，可以在本地或私有环境微调开源模型。</li>
                        <li><strong class="text-indigo-500">行为对齐：</strong> 使模型的输出更符合预期，减少“胡说八道”。</li>
                    </ul>
                     <p>简单来说，微调就是让“通才”模型变成特定领域的“专才”。</p>
                </section>

                <section id="scope" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                    <h2 class="text-2xl font-semibold text-indigo-600 mb-4">微调范围与原则：选择合适的模型</h2>
                    <p class="mb-4">理论上，市面上几乎所有的<strong class="text-green-600">开源大模型</strong>（如 Llama 系列, GLM-3, 通义千问系列等）都可以进行微调。但如何选择呢？关键在于平衡效果、成本和数据安全。</p>

                    <div class="border border-gray-200 rounded-lg p-4">
                        <h3 class="text-lg font-semibold mb-3 text-center">决策流程：选择微调路径</h3>
                        <div id="decision-tree" class="space-y-4 text-center">
                            <div class="p-3 bg-indigo-100 rounded-md shadow">需要微调 LLM 吗？</div>
                            <div class="flex justify-center gap-4">
                                <button onclick="showDecision('yes')" class="px-4 py-2 bg-green-500 text-white rounded hover:bg-green-600 transition">是</button>
                                <button onclick="showDecision('no')" class="px-4 py-2 bg-gray-400 text-white rounded hover:bg-gray-500 transition">否</button>
                            </div>
                            <div id="decision-no" class="hidden p-3 bg-gray-100 rounded-md shadow fade-in">
                                <p>👍 直接使用预训练模型。</p>
                            </div>
                            <div id="decision-yes" class="hidden space-y-4 fade-in">
                                <div class="p-3 bg-yellow-100 rounded-md shadow">数据安全/隐私要求极高？</div>
                                <div class="flex justify-center gap-4">
                                    <button onclick="showPath('secure')" class="px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 transition">是 (强隐私)</button>
                                    <button onclick="showPath('flexible')" class="px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition">否 (相对灵活)</button>
                                </div>
                                <div id="path-secure" class="hidden p-4 bg-red-50 rounded-md shadow fade-in">
                                    <p class="font-semibold text-red-700">🛡️ 最佳选择：</p>
                                    <ul class="list-disc list-inside text-left mx-auto max-w-md">
                                        <li>选择<strong class="text-green-700">开源</strong>大模型。</li>
                                        <li>进行<strong class="text-red-700">私有化部署</strong> (本地/公司内网)。</li>
                                        <li>在<strong class="text-red-700">私域环境</strong>中完成微调。</li>
                                    </ul>
                                    <p class="mt-2 text-sm text-red-600">原则：最大程度减少数据传输和第三方泄露风险。</p>
                                </div>
                                <div id="path-flexible" class="hidden p-4 bg-blue-50 rounded-md shadow fade-in">
                                     <p class="font-semibold text-blue-700">💡 灵活选择：</p>
                                     <ul class="list-disc list-inside text-left mx-auto max-w-md">
                                         <li>使用<strong class="text-blue-700">线上平台</strong>提供的算力进行微调 (注意平台的数据政策)。</li>
                                         <li>调用<strong class="text-purple-700">闭源模型 API</strong>进行微调 (如 OpenAI API，需上传数据)。</li>
                                         <li>在云端或本地微调<strong class="text-green-700">开源</strong>模型。</li>
                                     </ul>
                                     <p class="mt-2 text-sm text-blue-600">场景：学习研究、数据敏感度不高的应用、利用新用户福利等。</p>
                                </div>
                            </div>
                        </div>
                    </div>
                     <p class="mt-4 text-sm text-gray-600">核心原则：始终关注<strong class="text-red-600">数据安全</strong>，评估数据在传输、存储、处理过程中的泄露风险。</p>
                </section>

                 <section id="methods-overview" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                    <h2 class="text-2xl font-semibold text-indigo-600 mb-4">微调方法概览</h2>
                    <p class="mb-4">大模型微调的方法多种多样，主要可以分为三大类：</p>
                    <div class="flex flex-col md:flex-row justify-around items-center gap-4 p-4 border border-gray-200 rounded-lg">
                        <div class="text-center p-4 bg-red-50 rounded-lg shadow hover:shadow-lg transition w-full md:w-auto">
                            <h3 class="text-lg font-semibold text-red-700">1. 全量微调</h3>
                            <p class="text-sm text-red-600">(Full Fine-tuning)</p>
                            <p class="text-xs mt-1">训练所有参数</p>
                        </div>
                        <div class="text-center p-4 bg-blue-50 rounded-lg shadow hover:shadow-lg transition w-full md:w-auto">
                            <h3 class="text-lg font-semibold text-blue-700">2. 高效微调</h3>
                             <p class="text-sm text-blue-600">(PEFT: Parameter-Efficient Fine-tuning)</p>
                             <p class="text-xs mt-1">只训练部分参数或新增小模块</p>
                        </div>
                        <div class="text-center p-4 bg-green-50 rounded-lg shadow hover:shadow-lg transition w-full md:w-auto">
                            <h3 class="text-lg font-semibold text-green-700">3. 强化学习</h3>
                            <p class="text-sm text-green-600">(RLHF: Reinforcement Learning from Human Feedback)</p>
                             <p class="text-xs mt-1">根据人类反馈优化</p>
                        </div>
                    </div>
                    <p class="mt-4">接下来，我们将重点介绍前两种方法，特别是市面上应用广泛的 PEFT 技术。</p>
                </section>

                <section id="full-finetuning" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                    <h2 class="text-2xl font-semibold text-indigo-600 mb-4">1. 全量微调 (Full Fine-tuning)</h2>
                    <p class="mb-4">全量微调是指在预训练模型的基础上，使用特定任务的数据<strong class="text-red-600">重新训练模型的所有参数</strong>（权重、偏置等）。想象一下，模型的所有“神经元连接”都需要根据新数据进行调整。</p>

                    <div class="flex flex-col md:flex-row gap-6 items-start">
                        <div class="w-full md:w-1/3 border p-4 rounded-lg bg-gray-50">
                            <h4 class="text-md font-semibold mb-2 text-center">模型结构示意</h4>
                            <div id="full-ft-model" class="space-y-1">
                                <div class="llm-layer frozen">Embedding Layer</div>
                                <div class="llm-layer frozen">Transformer Block 1</div>
                                <div class="llm-layer frozen">Transformer Block 2</div>
                                <div class="llm-layer frozen">...</div>
                                <div class="llm-layer frozen">Transformer Block N</div>
                                <div class="llm-layer frozen">Output Layer</div>
                            </div>
                            <button onclick="animateFullFinetuning()" class="mt-4 w-full px-4 py-2 bg-red-500 text-white rounded hover:bg-red-600 transition">开始全量微调</button>
                        </div>
                        <div class="w-full md:w-2/3">
                            <h4 class="text-md font-semibold mb-2">特点：</h4>
                            <ul class="list-disc list-inside space-y-2 mb-4">
                                <li><strong>优点:</strong>
                                    <ul class="list-circle list-inside ml-4 text-sm text-gray-700">
                                        <li><strong class="text-green-600">效果潜力大：</strong> 模型完全为特定任务“量身定制”，理论上效果最好。</li>
                                        <li><strong class="text-green-600">深度适配：</strong> 能更深入地理解和生成特定领域的知识。</li>
                                    </ul>
                                </li>
                                <li><strong>缺点:</strong>
                                    <ul class="list-circle list-inside ml-4 text-sm text-gray-700">
                                        <li><strong class="text-red-600">成本极高：</strong> 需要大量的计算资源（GPU）、时间和数据。</li>
                                        <li><strong class="text-red-600">训练时间长：</strong> 微调过程可能耗时数天甚至数周。</li>
                                        <li><strong class="text-red-600">易过拟合 (Overfitting)：</strong> 模型可能过于“记住”训练数据，泛化能力下降。
                                            <span class="text-xs block text-gray-500">（例子：你告诉模型你叫“慕言”，之后无论问什么，它都可能只回答“你叫慕言”，失去了通用对话能力）。</span>
                                        </li>
                                         <li><strong class="text-red-600">模型体积大：</strong> 微调后需要存储整个模型的副本，管理困难。</li>
                                    </ul>
                                </li>
                            </ul>
                            <p class="text-sm text-gray-600"><strong>适用场景：</strong> 资源充足、对特定任务效果要求极高、且能接受高成本的公司或研究机构。对于大多数应用而言，全量微调并不常见。</p>
                        </div>
                    </div>
                </section>

                 <section id="peft-overview" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                    <h2 class="text-2xl font-semibold text-indigo-600 mb-4">2. PEFT 高效微调 (Parameter-Efficient Fine-tuning)</h2>
                    <p class="mb-4">鉴于全量微调的高昂成本，研究者们提出了参数高效微调（PEFT）方法。其核心思想是：<strong class="text-blue-600">冻结预训练模型的大部分参数，只调整其中一小部分参数或增加少量额外的可训练模块</strong>。这样既能实现模型对特定任务的适配，又能显著降低计算和存储成本。</p>
                    <p class="mb-4">PEFT 主要有以下几个流派：</p>
                    <div class="grid grid-cols-1 md:grid-cols-3 gap-4">
                        <div class="p-4 border border-blue-200 rounded-lg bg-blue-50 text-center shadow">
                            <h3 class="font-semibold text-blue-700">模型微调</h3>
                            <p class="text-sm text-gray-600">调整模型内部<strong class="text-blue-600">部分</strong>现有参数。</p>
                            <p class="text-xs mt-1">(如：冻结微调)</p>
                        </div>
                         <div class="p-4 border border-orange-200 rounded-lg bg-orange-50 text-center shadow">
                            <h3 class="font-semibold text-orange-700">提示微调</h3>
                             <p class="text-sm text-gray-600">在输入端加入<strong class="text-orange-600">可训练的</strong>提示向量。</p>
                             <p class="text-xs mt-1">(如：Prefix-Tuning, Prompt-Tuning, P-Tuning)</p>
                        </div>
                         <div class="p-4 border border-purple-200 rounded-lg bg-purple-50 text-center shadow">
                            <h3 class="font-semibold text-purple-700">外部模块微调</h3>
                             <p class="text-sm text-gray-600">在模型中插入<strong class="text-purple-600">额外的</strong>小型可训练模块。</p>
                             <p class="text-xs mt-1">(如：Adapter, LoRA)</p>
                        </div>
                    </div>
                </section>

                 <section id="peft-model" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                    <h3 class="text-xl font-semibold text-blue-700 mb-4">PEFT - 模型微调：调整部分现有参数</h3>
                    <p class="mb-4">这类方法通过选择性地解冻和训练模型内部的一部分层或参数来实现微调。</p>
                     <div class="flex flex-col md:flex-row gap-6 items-start">
                         <div class="w-full md:w-1/3 border p-4 rounded-lg bg-gray-50">
                             <h4 class="text-md font-semibold mb-2 text-center">模型结构示意</h4>
                             <div id="peft-model-layers" class="space-y-1">
                                <div class="llm-layer frozen" data-layer="embedding">Embedding Layer</div>
                                <div class="llm-layer frozen" data-layer="block1">Transformer Block 1</div>
                                <div class="llm-layer frozen" data-layer="block2">Transformer Block 2</div>
                                <div class="llm-layer frozen" data-layer="blockdots">...</div>
                                <div class="llm-layer frozen" data-layer="blockN">Transformer Block N</div>
                                <div class="llm-layer frozen" data-layer="output">Output Layer</div>
                             </div>
                             <div class="mt-4 space-y-2">
                                 <button onclick="animatePeftModel('top-layer', this)" class="w-full px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition text-sm">顶层微调</button>
                                 <button onclick="animatePeftModel('layer-wise', this)" class="w-full px-4 py-2 bg-blue-500 text-white rounded hover:bg-blue-600 transition text-sm">逐层微调 (动画)</button>
                                 <button onclick="animatePeftModel('reset', this)" class="w-full px-4 py-2 bg-gray-400 text-white rounded hover:bg-gray-500 transition text-sm">重置</button>
                             </div>
                             <p id="peft-model-desc" class="mt-3 text-xs text-center text-gray-500">点击按钮查看效果</p>
                         </div>
                         <div class="w-full md:w-2/3">
                             <dl class="space-y-3">
                                 <div>
                                     <dt class="font-semibold text-blue-600">冻结微调 (Freeze Fine-tuning)</dt>
                                     <dd class="text-sm text-gray-700 pl-4">
                                         <p><strong>顶层微调：</strong> 只训练模型的最后几层（如输出层），冻结其他所有层。假设高层负责具体任务，底层负责通用特征。</p>
                                         <p><strong>优点：</strong> 简单、快速、资源消耗少。</p>
                                         <p><strong>缺点：</strong> 可能效果有限，因为底层特征未调整。</p>
                                     </dd>
                                 </div>
                                  <div>
                                     <dt class="font-semibold text-blue-600">逐层微调 (Layer-wise Fine-tuning)</dt>
                                     <dd class="text-sm text-gray-700 pl-4">
                                         <p>逐个解冻并训练模型的层。例如，先训练输出层（冻结其他），再训练倒数第二层（冻结其他），依此类推。</p>
                                          <p><strong>优点：</strong> 比顶层微调更深入，可能效果更好。</p>
                                          <p><strong>缺点：</strong> 更复杂，训练时间更长。</p>
                                     </dd>
                                 </div>
                                 <div>
                                     <dt class="font-semibold text-blue-600">动态微调 (Dynamic Fine-tuning)</dt>
                                      <dd class="text-sm text-gray-700 pl-4">
                                          <p>在训练过程中根据需要动态地选择哪些层进行微调，可能基于梯度、损失等信息。例如，发现第 100 层的调整对第 97 层影响大，就同时调整 97 层。</p>
                                          <p><strong>优点：</strong> 可能更智能、高效。</p>
                                          <p><strong>缺点：</strong> 实现复杂，需要精巧的策略。</p>
                                      </dd>
                                 </div>
                             </dl>
                             <p class="mt-4 text-sm text-gray-600"><strong>总结：</strong> 这类方法直接操作模型内部参数，相对直观，但选择哪些层、如何训练需要经验和实验。操作难度和资源消耗介于全量微调和后面介绍的方法之间。</p>
                         </div>
                     </div>
                </section>

                 <section id="peft-prompt" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                    <h3 class="text-xl font-semibold text-orange-700 mb-4">PEFT - 提示微调：玩转输入提示</h3>
                    <p class="mb-4">这类方法的核心思想是：<strong class="text-orange-600">保持预训练模型完全冻结</strong>，通过在输入端添加或修改一些<strong class="text-orange-600">可训练的</strong>“软提示”（Soft Prompts，即连续的向量）来引导模型适应新任务。这就像给模型一个“秘籍”或“咒语”，告诉它如何处理特定的输入。</p>

                    <div class="mb-8 p-4 border border-orange-200 rounded-lg bg-orange-50">
                        <h4 class="text-lg font-semibold text-orange-600 mb-3">Prefix-Tuning</h4>
                         <div class="flex flex-col md:flex-row gap-6 items-start">
                             <div class="w-full md:w-1/3">
                                 <p class="text-sm text-gray-700 mb-2">在<strong class="text-red-600">每一层</strong> Transformer Block 前添加可训练的前缀向量 (P)。</p>
                                 <div id="prefix-tuning-model" class="space-y-1 border p-2 rounded bg-white">
                                     <div class="llm-layer frozen">Input + Embedding</div>
                                     <div class="flex items-center gap-1"> <span class="prompt-vector trainable">P</span> <div class="llm-layer frozen flex-1">Transformer Block 1</div></div>
                                     <div class="flex items-center gap-1"> <span class="prompt-vector trainable">P</span> <div class="llm-layer frozen flex-1">Transformer Block 2</div></div>
                                     <div class="text-center text-gray-500">...</div>
                                     <div class="flex items-center gap-1"> <span class="prompt-vector trainable">P</span> <div class="llm-layer frozen flex-1">Transformer Block N</div></div>
                                     <div class="llm-layer frozen">Output Layer</div>
                                 </div>
                             </div>
                             <div class="w-full md:w-2/3">
                                 <p class="text-sm text-gray-700 mb-2"><strong>原理：</strong> 冻结 LLM，为每个任务学习一个特定的连续向量前缀。这个前缀会影响模型在每一层的计算，引导其生成特定任务的输出。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>类比：</strong> 就像一个只会做“刀削面”的专卖店。无论顾客点什么（输入图片是猫还是车），它都会在处理流程的每一步都想着“刀削面”（加上固定前缀），最终输出与“刀削面”相关的结果（如将猫理解为“猫型刀削面”或“猫型汽车”，如果前缀是“汽车”）。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>特点：</strong></p>
                                 <ul class="list-disc list-inside text-xs space-y-1 ml-4">
                                     <li>针对<strong class="text-orange-600">特定任务</strong>效果较好。</li>
                                     <li>比全量微调参数少，但仍需在<strong class="text-red-600">每一层</strong>添加参数。</li>
                                     <li>灵活性差，一个前缀对应一个任务。</li>
                                 </ul>
                             </div>
                         </div>
                    </div>

                    <div class="mb-8 p-4 border border-orange-200 rounded-lg bg-orange-50">
                        <h4 class="text-lg font-semibold text-orange-600 mb-3">Prompt-Tuning</h4>
                         <div class="flex flex-col md:flex-row gap-6 items-start">
                             <div class="w-full md:w-1/3">
                                 <p class="text-sm text-gray-700 mb-2">只在<strong class="text-green-600">输入层</strong>添加 K 个可训练的提示向量 (E)。</p>
                                 <div id="prompt-tuning-model" class="space-y-1 border p-2 rounded bg-white">
                                      <div class="flex items-center gap-1 justify-center mb-1">
                                          <span class="prompt-vector trainable text-xs">E1</span>
                                          <span class="prompt-vector trainable text-xs">...</span>
                                          <span class="prompt-vector trainable text-xs">Ek</span>
                                          <span class="text-gray-600 mx-1">+</span>
                                          <span class="text-sm font-medium bg-gray-200 px-2 py-1 rounded">原始输入</span>
                                      </div>
                                     <div class="llm-layer frozen">Embedding Layer</div>
                                     <div class="llm-layer frozen">Transformer Block 1</div>
                                     <div class="llm-layer frozen">Transformer Block 2</div>
                                     <div class="text-center text-gray-500">...</div>
                                     <div class="llm-layer frozen">Transformer Block N</div>
                                     <div class="llm-layer frozen">Output Layer</div>
                                 </div>
                             </div>
                             <div class="w-full md:w-2/3">
                                 <p class="text-sm text-gray-700 mb-2"><strong>原理：</strong> 冻结 LLM，只学习几个添加到输入嵌入中的连续向量。这些向量相当于为特定任务“量身定做”的指令前缀。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>类比：</strong> 像一个有固定菜单（比如“刀削面”、“牛肉面”、“小炒肉”）的快餐店。顾客需要准确说出菜单上的菜名（输入与训练时完全匹配的提示），店家才能做出对应的菜（模型才能正确执行任务）。如果菜单上只有“家用小轿车”图片描述任务，你输入“家用 SUV”图片，效果就不好。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>特点：</strong></p>
                                 <ul class="list-disc list-inside text-xs space-y-1 ml-4">
                                     <li><strong class="text-green-600">参数效率极高</strong>，只训练很少的参数。</li>
                                     <li>训练<strong class="text-green-600">速度快</strong>，存储成本低。</li>
                                     <li>对提示的<strong class="text-red-600">措辞非常敏感</strong>，需要精确匹配。</li>
                                     <li>对于复杂任务或小模型，效果可能不如其他方法。</li>
                                 </ul>
                             </div>
                         </div>
                    </div>

                     <div class="p-4 border border-orange-200 rounded-lg bg-orange-50">
                        <h4 class="text-lg font-semibold text-orange-600 mb-3">P-Tuning (v2)</h4>
                         <div class="flex flex-col md:flex-row gap-6 items-start">
                             <div class="w-full md:w-1/3">
                                 <p class="text-sm text-gray-700 mb-2">类似 Prefix-Tuning，在<strong class="text-red-600">每一层</strong>加入可训练向量，但使用 MLP 等结构生成，更稳定通用。</p>
                                  <div id="p-tuning-model" class="space-y-1 border p-2 rounded bg-white">
                                     <div class="llm-layer frozen">Input + Embedding</div>
                                     <div class="flex items-center gap-1"> <span class="prompt-vector trainable bg-yellow-500">PT</span> <div class="llm-layer frozen flex-1">Transformer Block 1</div></div>
                                     <div class="flex items-center gap-1"> <span class="prompt-vector trainable bg-yellow-500">PT</span> <div class="llm-layer frozen flex-1">Transformer Block 2</div></div>
                                     <div class="text-center text-gray-500">...</div>
                                     <div class="flex items-center gap-1"> <span class="prompt-vector trainable bg-yellow-500">PT</span> <div class="llm-layer frozen flex-1">Transformer Block N</div></div>
                                     <div class="llm-layer frozen">Output Layer</div>
                                 </div>
                             </div>
                             <div class="w-full md:w-2/3">
                                 <p class="text-sm text-gray-700 mb-2"><strong>原理：</strong> 旨在克服 Prompt-Tuning 的不稳定性，并提升其在不同模型规模和任务上的表现。通过在模型的<strong class="text-red-600">每一层</strong>都引入可优化的连续提示向量（类似 Prefix-Tuning），但通常使用更强大的机制（如 MLP）来生成和优化这些向量，使其能更好地指导模型内部的表示。</p>
                                  <p class="text-sm text-gray-700 mb-2"><strong>类比：</strong> 像一个经验丰富的厨师。不仅能根据菜单做菜（处理标准提示），还能理解顾客的模糊要求（“炒个绿色的菜花” -> 理解为炒西兰花），甚至能根据要求调整口味（“多加辣”、“少放盐”、“多加汤”）。它对输入的理解更深入、更灵活。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>特点：</strong></p>
                                 <ul class="list-disc list-inside text-xs space-y-1 ml-4">
                                     <li>效果通常<strong class="text-green-600">优于</strong> Prompt-Tuning 和 Prefix-Tuning。</li>
                                     <li>在不同模型大小和任务上<strong class="text-green-600">更稳定、通用</strong>。</li>
                                     <li>参数量介于 Prompt-Tuning 和全量微调之间，比 Prompt-Tuning 多。</li>
                                      <li>实现相对复杂一些。</li>
                                 </ul>
                             </div>
                         </div>
                    </div>
                </section>

                 <section id="peft-adapter" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                     <h3 class="text-xl font-semibold text-purple-700 mb-4">PEFT - 外部模块微调：添加“插件”</h3>
                    <p class="mb-4">这类方法通过在预训练模型的固定结构中<strong class="text-purple-600">插入</strong>一些小型的、可训练的“外部”模块来实现微调，而<strong class="text-gray-500">不改变</strong>原有的模型参数。</p>

                    <div class="mb-8 p-4 border border-purple-200 rounded-lg bg-purple-50">
                        <h4 class="text-lg font-semibold text-purple-600 mb-3">Adapter Tuning</h4>
                         <div class="flex flex-col md:flex-row gap-6 items-start">
                             <div class="w-full md:w-1/3">
                                 <p class="text-sm text-gray-700 mb-2">在 Transformer Block <strong class="text-blue-600">内部</strong>（通常是 FeedForward 层之后或 Attention 层之后）插入 Adapter 模块。</p>
                                 <div id="adapter-tuning-model" class="space-y-1 border p-2 rounded bg-white">
                                     <div class="llm-layer frozen">...</div>
                                     <div class="llm-layer frozen">Transformer Block (Partial)</div>
                                     <div class="relative my-2 flex flex-col items-center">
                                         <div class="text-xs text-gray-500 mb-1">↓ Input</div>
                                         <div class="adapter-module trainable">
                                             <span>降维</span>
                                             <span>升维</span>
                                         </div>
                                         <div class="text-xs text-gray-500 mt-1">↓ Output to next part</div>
                                         <div class="absolute left-0 top-0 bottom-0 w-px bg-gray-400 -translate-x-4"></div>
                                         <div class="absolute right-0 top-0 bottom-0 w-px bg-gray-400 translate-x-4"></div>
                                         <div class="absolute left-0 right-0 top-1/2 h-px bg-gray-400 -translate-x-4 w-4"></div>
                                         <div class="absolute left-0 right-0 top-1/2 h-px bg-gray-400 translate-x-16 w-4"></div>
                                         <span class="absolute top-1/2 -left-6 text-xs text-gray-500 -translate-y-1/2 transform rotate-90">Skip</span>
                                     </div>
                                     <div class="llm-layer frozen">Transformer Block (Rest)</div>
                                     <div class="llm-layer frozen">...</div>
                                 </div>
                             </div>
                             <div class="w-full md:w-2/3">
                                 <p class="text-sm text-gray-700 mb-2"><strong>原理：</strong> 冻结 LLM 主体。在模型的某些层之间插入小的、瓶颈结构（先降维再升维）的 Adapter 模块。只训练这些 Adapter 模块的参数。通常还有一个<strong class="text-gray-600">残差连接 (Skip Connection)</strong>，允许原始信息直接通过，保证即使 Adapter 没学好，模型性能也不会下降。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>降维再升维的目的：</strong> 假设模型内部的高维表示中，与特定任务相关的有用信息实际存在于一个低维子空间。Adapter 先将信息压缩到低维（降维），学习关键特征，然后再恢复到原始维度（升维），以便与模型的其他部分兼容。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>特点：</strong></p>
                                 <ul class="list-disc list-inside text-xs space-y-1 ml-4">
                                     <li><strong class="text-green-600">参数效率高</strong>，只训练少量 Adapter 参数。</li>
                                     <li>可以为不同任务训练<strong class="text-green-600">不同的 Adapter</strong>，按需加载，灵活性好。</li>
                                     <li>插入位置和 Adapter 结构会影响效果。</li>
                                 </ul>
                             </div>
                         </div>
                    </div>

                    <div class="p-4 border border-purple-200 rounded-lg bg-purple-50">
                        <h4 class="text-lg font-semibold text-purple-600 mb-3">LoRA (Low-Rank Adaptation)</h4>
                         <div class="flex flex-col md:flex-row gap-6 items-start">
                             <div class="w-full md:w-1/3">
                                 <p class="text-sm text-gray-700 mb-2">冻结原始权重矩阵 W，引入两个<strong class="text-purple-600">低秩</strong>矩阵 A 和 B，只训练 A 和 B。最终的权重是 W + B*A。</p>
                                 <div id="lora-tuning-model" class="flex flex-col items-center justify-center border p-4 rounded bg-white h-40">
                                     <div class="flex items-center gap-2">
                                         <div class="llm-layer frozen w-20 h-20 flex items-center justify-center text-xl">W</div>
                                         <span class="text-2xl font-light text-gray-600">+</span>
                                         <div class="flex gap-1">
                                             <div class="lora-matrix trainable w-8 h-20 flex items-center justify-center text-xl">B</div>
                                             <div class="lora-matrix trainable w-20 h-8 flex items-center justify-center text-xl mt-12 -ml-8">A</div>
                                         </div>
                                     </div>
                                      <p class="text-xs text-gray-500 mt-2">W (冻结) + B*A (训练)</p>
                                 </div>
                             </div>
                             <div class="w-full md:w-2/3">
                                 <p class="text-sm text-gray-700 mb-2"><strong>原理：</strong> 基于一个假设：模型在微调时，权重的<strong class="text-purple-600">改变量 (ΔW)</strong> 通常是低秩的。也就是说，虽然原始权重矩阵 W 很大，但需要调整的部分可以用两个小得多的矩阵 B 和 A 的乘积来近似 (ΔW ≈ B * A)。因此，LoRA 冻结 W，只学习并存储 B 和 A。推理时，可以直接将 B*A 加到 W 上，或者分开计算。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>类比：</strong> 想象调整一个巨大的混音台（原始权重 W）。LoRA 发现，你通常只需要动几个关键的推子组合（矩阵 B 和 A）就能达到想要的效果，而不需要碰其他的几百个按钮。</p>
                                 <p class="text-sm text-gray-700 mb-2"><strong>特点：</strong></p>
                                 <ul class="list-disc list-inside text-xs space-y-1 ml-4">
                                     <li><strong class="text-green-600">极高的参数效率</strong>，训练参数非常少 (r 通常很小)。</li>
                                     <li>训练<strong class="text-green-600">速度快</strong>，存储成本极低 (只需存 B 和 A)。</li>
                                     <li>切换任务<strong class="text-green-600">非常方便</strong>，只需加载不同的 LoRA 权重 (B, A)。</li>
                                     <li>效果通常<strong class="text-green-600">接近或持平</strong>全量微调。</li>
                                     <li>目前<strong class="text-green-600">非常流行</strong>的 PEFT 方法。</li>
                                 </ul>
                                  <p class="text-xs text-gray-500 mt-2">注：后续课程会详细讲解 LoRA 的原理和实战。</p>
                             </div>
                         </div>
                    </div>
                </section>

                 <section id="rlhf" class="mb-12 p-6 bg-white rounded-lg shadow-md scroll-mt-20">
                    <h2 class="text-2xl font-semibold text-indigo-600 mb-4">3. 强化学习 (RLHF)</h2>
                    <p class="mb-4">强化学习，特别是基于人类反馈的强化学习 (RLHF)，是另一种重要的微调技术，但其目标与前面介绍的方法略有不同。RLHF 主要用于<strong class="text-green-600">对齐 (Alignment)</strong> 模型，使其行为更符合人类的偏好、价值观，并提高其有用性、诚实性和无害性。</p>
                     <div class="flex items-center justify-center gap-4 p-4 border border-green-200 rounded-lg bg-green-50">
                         <svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-green-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                           <path stroke-linecap="round" stroke-linejoin="round" d="M14.828 14.828a4 4 0 01-5.656 0M9 10h.01M15 10h.01M21 12a9 9 0 11-18 0 9 9 0 0118 0z" />
                           <path stroke-linecap="round" stroke-linejoin="round" d="M16 12a4 4 0 11-8 0 4 4 0 018 0z" /> /* Simplified human feedback icon */
                         </svg>
                         <span class="text-gray-600 text-xl font-light">→</span>
                         <svg xmlns="http://www.w3.org/2000/svg" class="h-10 w-10 text-indigo-600" fill="none" viewBox="0 0 24 24" stroke="currentColor" stroke-width="2">
                            <path stroke-linecap="round" stroke-linejoin="round" d="M9.75 17L9 20l-1 1h8l-1-1-.75-3M3 13h18M5 17h14a2 2 0 002-2V5a2 2 0 00-2-2H5a2 2 0 00-2 2v10a2 2 0 002 2z" /> /* Simplified AI/Model icon */
                         </svg>
                         <span class="text-gray-600 text-xl font-light">→</span>
                         <span class="text-green-700 font-semibold">更优行为</span>
                     </div>
                    <p class="mt-4 text-sm text-gray-700">RLHF 通常涉及三个步骤：</p>
                    <ol class="list-decimal list-inside space-y-1 text-sm text-gray-600">
                        <li>训练一个初始的语言模型 (通常经过监督微调)。</li>
                        <li>收集人类对模型输出的偏好数据 (例如，对两个回答进行排序)。</li>
                        <li>训练一个奖励模型 (Reward Model) 来预测哪个输出更符合人类偏好。</li>
                        <li>使用强化学习算法 (如 PPO) 根据奖励模型的信号进一步微调语言模型。</li>
                    </ol>
                    <p class="mt-2 text-sm text-gray-600">RLHF 对于提高模型的安全性和可靠性至关重要，但过程相对复杂。</p>
                </section>

                <section id="summary" class="p-6 bg-indigo-50 rounded-lg shadow-md scroll-mt-20">
                    <h2 class="text-2xl font-semibold text-indigo-600 mb-4">总结：选择合适的微调策略</h2>
                    <p class="mb-4">我们探讨了多种大模型微调方法，从资源密集的全量微调到灵活高效的 PEFT 技术。选择哪种方法取决于您的具体需求：</p>
                    <ul class="list-disc list-inside space-y-2 text-gray-700">
                        <li><strong>追求极致领域效果，且资源充足？</strong> 考虑 <strong class="text-red-600">全量微调</strong> (但需注意成本和过拟合风险)。</li>
                        <li><strong>资源有限，希望快速适配任务？</strong> <strong class="text-blue-600">PEFT</strong> 是主流选择。
                            <ul class="list-circle list-inside ml-6 text-sm space-y-1">
                                <li>需要极高参数效率、快速切换任务？ <strong class="text-purple-600">LoRA</strong> 是当前热门且有效的选择。</li>
                                <li>需要为不同任务管理独立模块？<strong class="text-purple-600">Adapter</strong> 提供了很好的模块化方案。</li>
                                <li>希望通过优化提示来引导模型？<strong class="text-orange-600">P-Tuning (v2)</strong> 提供了较好的效果和稳定性，<strong class="text-orange-600">Prompt-Tuning</strong> 参数最少但较敏感，<strong class="text-orange-600">Prefix-Tuning</strong> 适用于非常特定的任务。</li>
                                 <li>希望调整模型内部结构但又想节省资源？<strong class="text-blue-600">冻结微调</strong> (如顶层微调) 是简单尝试。</li>
                            </ul>
                        </li>
                        <li><strong>关注模型行为对齐、安全性和可靠性？</strong> <strong class="text-green-600">RLHF</strong> 是关键技术 (通常结合其他微调方法使用)。</li>
                    </ul>
                    <p class="mt-4">理解这些方法的原理、优缺点和适用场景，将帮助您在实际应用中做出明智的选择，高效地利用大模型解决特定问题。</p>
                </section>
            </main>
        </div>
    </div>

    <script>
        // --- 决策树交互 ---
        function showDecision(choice) {
            document.getElementById('decision-no').classList.add('hidden');
            document.getElementById('decision-yes').classList.add('hidden');
            document.getElementById('path-secure').classList.add('hidden');
            document.getElementById('path-flexible').classList.add('hidden');

            if (choice === 'yes') {
                document.getElementById('decision-yes').classList.remove('hidden');
            } else {
                document.getElementById('decision-no').classList.remove('hidden');
            }
        }

        function showPath(path) {
            document.getElementById('path-secure').classList.add('hidden');
            document.getElementById('path-flexible').classList.add('hidden');
            document.getElementById(`path-${path}`).classList.remove('hidden');
        }

        // --- 全量微调动画 ---
        function animateFullFinetuning() {
            const layers = document.querySelectorAll('#full-ft-model .llm-layer');
            layers.forEach(layer => {
                layer.classList.remove('frozen');
                layer.classList.add('trainable', 'bg-green-100', 'border-green-500'); // Change style to indicate training
            });
            // Optional: Add a reset button or timeout to revert styles
        }

        // --- PEFT 模型微调动画 ---
        let layerWiseInterval; // Store interval ID for layer-wise animation
        function animatePeftModel(type, button) {
            const layers = document.querySelectorAll('#peft-model-layers .llm-layer');
            const desc = document.getElementById('peft-model-desc');
            const buttons = document.querySelectorAll('#peft-model section button');

            // Reset styles and interval first
            clearInterval(layerWiseInterval);
            layers.forEach(layer => {
                layer.classList.remove('trainable', 'bg-green-100', 'border-green-500');
                layer.classList.add('frozen');
            });
             buttons.forEach(btn => btn.classList.remove('active-btn')); // Remove active class from all buttons

            if (button && type !== 'reset') {
                 button.classList.add('active-btn'); // Add active class to the clicked button
            }


            if (type === 'top-layer') {
                const outputLayer = document.querySelector('#peft-model-layers [data-layer="output"]');
                if (outputLayer) {
                    outputLayer.classList.remove('frozen');
                    outputLayer.classList.add('trainable', 'bg-green-100', 'border-green-500');
                }
                 desc.textContent = "只训练输出层 (绿色高亮)";
            } else if (type === 'layer-wise') {
                const layerOrder = ['output', 'blockN', 'blockdots', 'block2', 'block1', 'embedding']; // Reverse order for animation
                let i = 0;
                desc.textContent = "逐层解冻训练 (从上到下)...";

                layerWiseInterval = setInterval(() => {
                    if (i < layerOrder.length) {
                         // Reset previous layer's highlight slightly
                        if (i > 0) {
                             const prevLayer = document.querySelector(`#peft-model-layers [data-layer="${layerOrder[i-1]}"]`);
                             if(prevLayer) prevLayer.classList.replace('bg-green-100','bg-green-50'); // Keep border, slightly fade bg
                        }

                        const currentLayer = document.querySelector(`#peft-model-layers [data-layer="${layerOrder[i]}"]`);
                        if (currentLayer) {
                            currentLayer.classList.remove('frozen');
                            currentLayer.classList.add('trainable', 'bg-green-100', 'border-green-500'); // Highlight current layer
                        }
                        i++;
                    } else {
                        clearInterval(layerWiseInterval);
                         desc.textContent = "逐层微调完成";
                    }
                }, 800); // Adjust speed as needed
            } else if (type === 'reset') {
                 desc.textContent = "点击按钮查看效果";
            }
        }

        // --- Smooth Scrolling for Nav Links ---
        document.querySelectorAll('nav a[href^="#"]').forEach(anchor => {
            anchor.addEventListener('click', function (e) {
                e.preventDefault();
                const targetId = this.getAttribute('href');
                const targetElement = document.querySelector(targetId);
                if(targetElement){
                    targetElement.scrollIntoView({
                        behavior: 'smooth'
                    });
                }
            });
        });

    </script>

</body>
</html>
